package mycrypto

import (
	"crypto/rand"
	"crypto/sha256"
	"encoding/pem"
	"fmt"
	"math/big"
	"os"

	"github.com/Hyperledger-TWGC/ccs-gm/sm2"
	"github.com/Hyperledger-TWGC/ccs-gm/utils"
)

// GenerateSM2KeyPair ...
func GenerateSM2KeyPair() {
	//生成密钥对
	privateKey, err := sm2.GenerateKey(rand.Reader)
	if err != nil {
		panic(err)
	}
	fmt.Println(privateKey)
	//保存私钥
	//生成文件
	privatefile, err := os.Create("sm2private.pem")
	if err != nil {
		panic(err)
	}
	priPEM, err := utils.PrivateKeyToPEM(privateKey, nil)
	if err != nil {
		panic(err)
	}
	privateBlock, _ := pem.Decode(priPEM)
	pem.Encode(privatefile, privateBlock)
	// 保存公钥
	publicKey := privateKey.PublicKey
	//创建文件
	publicfile, err := os.Create("sm2public.pem")
	if err != nil {
		panic(err)
	}
	pubPEM, err := utils.PublicKeyToPEM(&publicKey, nil)
	if err != nil {
		panic(err)
	}
	publicBlock, _ := pem.Decode(pubPEM)
	pem.Encode(publicfile, publicBlock)
}

// GetSM2PrivateKey ...
func GetSM2PrivateKey(path string) *sm2.PrivateKey {
	//读取私钥
	file, err := os.Open(path)
	if err != nil {
		panic(err)
	}
	defer file.Close()
	info, _ := file.Stat()
	buf := make([]byte, info.Size())
	file.Read(buf)
	//pem解码
	privateKey, _ := utils.PEMtoPrivateKey(buf, nil)
	fmt.Println(privateKey)
	return privateKey
}

// GetSM2PublicKey ...
func GetSM2PublicKey(path string) *sm2.PublicKey {
	//读取私钥
	file, err := os.Open(path)
	if err != nil {
		panic(err)
	}
	defer file.Close()
	info, _ := file.Stat()
	buf := make([]byte, info.Size())
	file.Read(buf)
	//pem解码
	publicKey, _ := utils.PEMtoPublicKey(buf, nil)
	fmt.Println(publicKey)
	return publicKey
}

// SM2Encrypt ...
func SM2Encrypt(msgBytes []byte, path string) ([]byte, error) {
	publicKey := GetSM2PublicKey(path)
	return sm2.Encrypt(rand.Reader, publicKey, msgBytes)
}

// SM2Decrypt ...
func SM2Decrypt(encData []byte, path string) ([]byte, error) {
	privateKey := GetSM2PrivateKey(path)
	return sm2.Decrypt(encData, privateKey)
}

// GetSM2Sign ...
func GetSM2Sign(msg []byte, path string) ([]byte, []byte) {
	//取得私钥
	privateKey := GetSM2PrivateKey(path)
	//计算哈希值
	hash := sha256.New()
	//填入数据
	hash.Write(msg)
	bytes := hash.Sum(nil)
	//对哈希值生成数字签名
	r, s, err := sm2.Sign(rand.Reader, privateKey, bytes)
	if err != nil {
		panic(err)
	}
	rtext, _ := r.MarshalText()
	stext, _ := s.MarshalText()
	return rtext, stext
}

// VerifySM2Sign ...
func VerifySM2Sign(msg []byte, rtext, stext []byte, path string) bool {
	//读取公钥
	publicKey := GetSM2PublicKey(path)
	//计算哈希值
	hash := sha256.New()
	hash.Write(msg)
	bytes := hash.Sum(nil)
	//验证数字签名
	var r, s big.Int
	r.UnmarshalText(rtext)
	s.UnmarshalText(stext)
	verify := sm2.Verify(publicKey, bytes, &r, &s)
	return verify
}
